<?php
define("DATA_OBJECT", "JunctionUser"); // define the name of the data object to be wrapped.

# require the Junction library and the JunctionUser class.

/**
 * Sample business object written as a wrapper around Junction.
 *
 * <p>This object is a business object which is written to encapsulate Junction's
 * functionality.  The goal is to allow application-specific business logic to be
 * implemented once in this object but delegate persistance-specific logic to the
 * Junction library.
 * <p>In addition to concentrating business logic, this class is responsible for
 * hiding state from the rest of the application.  It is necessary for Junction 
 * that all of the data object's state be exposed (through getters and setters)
 * but it may not be desirable to expose all of an object's state, or at least
 * to allow it all to be mutable.
 */
class BusinessUser {
	
	/**
	 * Junction data object which is being wrapped.
	 *
	 * @var JunctionUser
	 */
	private $_user;
	
	/**
	 * Public constructor for new users.
	 * 
	 * <p>Will construct a new user with the given email and password.
	 * The password will be hashed and a created date will be 
	 * automatically assigned.
	 *
	 * @param String $email
	 * @param String $password
	 */
	public function __construct($email, $password) {
		$this->_user = new JunctionUser();
		$this->_user->setEmail($email);
		$this->setPassword($password);
		$this->_user->setDate(time());
	}
	
	/**
	 * Retrieve the user object's id; It cannot be written to. 
	 *
	 * @return int
	 */
	public function getId() {
		return $this->_user->getId();
	}
	
	/**
	 * Retrieve the user object's email; It cannot be written to.
	 *
	 * @return String
	 */
	public function getEmail() {
		return $this->_user->getEmail();
	}
	
	/**
	 * Retrieve the password, which is the only mutable state.
	 *
	 * @return String a hashed password.
	 */
	public function getPassword() {
		return $this->_user->getPassword();
	}
	
	/**
	 * Assign a new password to the user hashing it first.
	 *
	 * @param String $password
	 */
	public function setPassword($password) {
		$this->_user->setPassword(md5($password));
	}
	
	/**
	 * Get the date the user was created as a formatted string.
	 *
	 * @return String
	 */
	public function getCreated() {
		return date('F j, Y', $this->_user->getDate());
	}
	
	/**
	 * Retrieve the internal Junction data object.
	 * 
	 * <p>This is used by the static methods to fetch and store
	 * user objects.
	 *
	 * @return JunctionUser
	 */
	private function getUser() {
		return $this->_user;
	}
	
	/**
	 * Set the internal Junction data object.
	 * 
	 * <p>This is used by the static methods to fetch and store
	 * user objects.
	 *
	 * @param JunctionUser $user
	 */
	private function setUser(JunctionUser $user) {
		$this->_user = $user;
	}
	
	/**
	 * Static alternate constructor used to create new business users.
	 * 
	 * <p>This method is public so that an iterator of BusinessUsers can
	 * be created. 
	 *
	 * @param JunctionUser $user
	 * @return BusinessUser
	 */
	public static function construct(JunctionUser $user) {
		$newUser = new BusinessUser(null, null);
		$newUser->setUser($user);
		return $newUser;
	}
	
	/**
	 * Retrieve a business user by its id.
	 * 
	 * @param int $id
	 * @return BusinessUser
	 */
	public static function fetchBy($id) {
		$junction = Junction::construct(DATA_OBJECT);
		$clause = $junction->createQuery("Id == ?");
		$clause->bind(0, $id);
		$users = $junction->loadWhere($clause);
		return self::construct($users->current());
	}
	
	/**
	 * Retrieve a collection of business users which match the given condition.
	 * 
	 * <p>The clause should be a string with placeholders, "?", for values and the
	 * args parameter should be an ordered array containing the arguments for the
	 * placeholders.
	 * 
	 * @param String $clause
	 * @param array $args
	 * @return BusinessUserIterator
	 */
	public static function fetchBy($clause, $args) {
		$junction = Junction::construct(DATA_OBJECT);
		$clause = $junction->createQuery($clause);
		foreach ($args as $key => $value) {
			$clause->bind($key, $value);
		}
		return new BusinessUserIterator($junction->loadWhere($clause));
	}
	
	/**
	 * Save the state of a given BusinessUser object.
	 * 
	 * <p>If the user has not been saved to the database before then its
	 * id will be assigned a value.
	 * 
	 * @param BusinessUser $user
	 * @return boolean
	 */
	public static function save(BusinessUser $user) {
		$junction = Junction::construct(DATA_OBJECT);
		return $junction->save($user->getUser());
	}
	
	/**
	 * Delete users who match the given condition.
	 * 
	 * @param String $clause
	 * @param array $args
	 * @return int
	 */
	public static function deleteWhere($clause, $args) {
		$junction = Junction::construct(DATA_OBJECT);
		$clause = $junction->createQuery($clause);
		foreach ($args as $key => $value) {
			$clause->bind($key, $value);
		}
		return $junction->deleteWhere($clause);
	}
}
?>